//* --------------------------------------------
//* Mouse Functions ----------------------------
//* --------------------------------------------
//* --------------------------------------------

void mouseClicked(){ 

  if(withinOptionBounds()) {
    float gridY = (optionY2 - optionY1) / nOption;
    if(selectedOption != (int)((mouseY - optionY1) / gridY)) {
      updateOption();
      loop();
    }
  }
  
  if(withinColoringBounds()) {
    float gridY = (coloringY2 - coloringY1) / nColoring;
    if(selectedColoring != (int)((mouseY - coloringY1) / gridY)) updateColoring();
    colorLayers();
    loop();
  }
 
 
   
  if(withinFilterBounds()){
    onFilter = true;
    calculateSelectedFilter();
//    for(int i=0; i< numFilters; i++){
//      if(filtersChosen[i] == 0)
//        controllerOld.setColor(i, 0x00000000);
//        int layerID = controller.matchLayerID(i);
//        controllerOld.setData(controller.getRealData(layerID, pos);
//    }
    setData(false);
    controllerPrev = controller;
    // sort layers
    controller.sort();
    addData();
    computeDataMinMax();
    colorLayers();
    setNumFiltersSlider();
    loop();
  }

  if(withinNumDivScrollBarBounds()) {
    numDivSliderPos = mouseX;
    confinenumDivSliderToBound();
    confineLSliderToSampleBound(5);
    confineRSliderToSampleBound(5);
    
    calculateNumDivisions();
    
  }
  
//  if(withinNumFiltersScrollBarBounds()) {
//    numFiltersSliderPos = mouseX;
//    confinenumFiltersSliderToBound();
//
//    calculateNumFilters();
//    
//  }
  
  if(!drawTrend() && mouseEvent.getClickCount() == 1 && withinMainPlotBounds() && dbclickedLayer == -1){
    println("ONE CLICK");
    int prevID = layerIDtoStroke;
    
    int low = (int)map(ltimeSliderPos, timeScrollBarX1, timeScrollBarX2, 0, controller.numData);
    int upper = (int)map(rtimeSliderPos, timeScrollBarX1, timeScrollBarX2, 0, controller.numData);  
    
    float m = (float)(mainPlotX2 - mainPlotX1) / (upper - low - 1);
    m *= 0.5;
   for (int layerID = 0; layerID < controller.numLayers; layerID++) {
    
    for(int pos = low; pos < upper; pos++){
      float u = controller.getUpperData(layerID, pos); //controller.getg0(pos) + controller.getUpperOffset(layerID, pos);
      float l = controller.getLowerData(layerID, pos); //controller.getg0(pos) + controller.getLowerOffset(layerID, pos);
      float x = map(pos, low, upper - 1, mainPlotX1, mainPlotX2);
      float yu = map(u, dataMin, dataMax, mainPlotY2 , mainPlotY1);
      float yl = map(l, dataMin, dataMax, mainPlotY2 , mainPlotY1);
      
      if (withinCustomBounds(x - m, x + m, yu, yl)){
       layerIDtoStroke = layerID;
      } 
    }
   }
   
   if(layerIDtoStroke != -1) controller.setStrokeColor(layerIDtoStroke, 0xFFFFFFFF);
   if(prevID != -1) controller.setStrokeColor(prevID, controller.getColor(prevID));
   if(prevID == layerIDtoStroke) layerIDtoStroke = -1;
   
   for (int layerID = 0; layerID < controller.numLayers; layerID++) {
     color c = controller.getColor(layerID);
     if(layerID != layerIDtoStroke){     
       if(layerIDtoStroke != -1) {
         controller.setColor(layerID, color(red(c), green(c), blue(c), 100));
         controller.setStrokeColor(layerID, color(red(c), green(c), blue(c), 0));
       }
       else {
         controller.setColor(layerID, color(red(c), green(c), blue(c), 255));
         controller.setStrokeColor(layerID, color(red(c), green(c), blue(c), 255));
       }
     }else if(layerID == layerIDtoStroke){
       controller.setColor(layerID, color(red(c), green(c), blue(c), 225));
       controller.setStrokeColor(layerID, color(red(c), green(c), blue(c), 255));
     }
   }
   
   loop();
  }
  
  if(overHueFlip()){
    isHueFlip++;
    if(isHueFlip == 4) {isHueFlip = 0;}
    colorLayers();
    
    loop();
  }
  
  if(overLumaFlip()){
    
    isLumaFlip++;
    if(isLumaFlip == 2) {isLumaFlip = 0;}
    colorLayers();
    
    loop();
  }
  
  if(overChromaFlip()){
    isChromaFlip++;
    if(isChromaFlip == 2) {isChromaFlip = 0;}
    colorLayers();
    
    loop();
  }
  
}

void mousePressed(){
  // + double click
 if (mouseEvent.getClickCount() == 2) {
   if (numFilteredColumns != 1){
      if(layerIDtoStroke == -1) return;
      int layerID = controllerPrev.matchLayerIDReverse(layerIDtoStroke);
      dbclickedLayer = 1;
      
      
      println("TWO CLICKS");
  
      setSelectedLayerFilter(layerID);
      setData(false);
      controllerPrev = controller;
  
      // sort layers
      controller.sort();
      addData();
      computeDataMinMax();
      
      colorLayers();
      setNumFiltersSlider();
      println("TWO CLICKS - OUT - AFTER COLOR LAYERS");
      layerIDtoStroke = -1;
      dbclickedLayer = -1;
      highlightedLayer = -1;
      loop();
   }else{
  
      println("TWO CLICKS ALL");
      setAllFiltersTrue();
      setData(false);
      controllerPrev = controller;
  
      // sort layers
      controller.sort();
      addData();
      computeDataMinMax();
      
      colorLayers();
      println("TWO CLICKS - OUT - AFTER COLOR LAYERS");
      layerIDtoStroke = -1;
      dbclickedLayer = -1;
      highlightedLayer = -1;
      loop();
     
   }
 }
 
  if(withinTimeScrollBarBounds()){
    if(overLTimeSlider()) isLTimeSlider = true;
    else if(overRTimeSlider()) isRTimeSlider = true;
    else if(betweenLRTimeSliders()){
      onSlider = true;
      devMouse_LeftSlider = mouseX - ltimeSliderPos + timeSliderDimX/2;
    }//
  }
  
  else if(withinHueScrollBarBounds()){
    if(overLHueSlider()) isLHueSlider = true;
    else if(overRHueSlider()) isRHueSlider = true;
    else if(betweenLRHueSliders()){
      onHueSlider = true;
      devMouse_LeftHueSlider = mouseX - lhueSliderPos + hueSliderDimX/2;
    }//
  }
  
  else if(withinLumaScrollBarBounds()){
    if(overLLumaSlider()) isLLumaSlider = true;
    else if(overRLumaSlider()) isRLumaSlider = true;
    else if(betweenLRLumaSliders()){
      onLumaSlider = true;
      devMouse_LeftLumaSlider = mouseX - llumaSliderPos + lumaSliderDimX/2;
    }//
  }
  
  else if(withinChromaScrollBarBounds()){
    if(overLChromaSlider()) isLChromaSlider = true;
    else if(overRChromaSlider()) isRChromaSlider = true;
    else if(betweenLRChromaSliders()){
      onChromaSlider = true;
      devMouse_LeftChromaSlider = mouseX - lchromaSliderPos + chromaSliderDimX/2;
    }//
  }
  
  if(withinNumDivScrollBarBounds()) onnumDivSlider = true;
  if(withinNumFiltersScrollBarBounds()){
    if(overLNumFiltersSlider()) isLNumFiltersSlider = true;
    else if(overRNumFiltersSlider()) isRNumFiltersSlider = true;
    else if(betweenLRNumFiltersSliders()){
      onNumFiltersSlider = true;
      devMouse_LeftNumFiltersSlider = mouseX - lnumFiltersSliderPos + numFiltersSliderDimX/2;
    }//
  }
}

void mouseDragged(){
  
  if(dbclickedLayer != -1) {
    if(withinTrendPlotBounds()) {
      // drag the trend view
      // TBD
    } else {
      dbclickedLayer = -1;
    }
  }
  
  if(isLTimeSlider){
    ltimeSliderPos = mouseX - timeSliderDimX/2;
    confineLSliderToBound(10);
    confineLSliderToSampleBound(5);
   
//    setData(false);
//    addData();
    loop();
  }
  
  else if(isRTimeSlider){
    rtimeSliderPos = mouseX - timeSliderDimX/2;
    confineRSliderToBound(10);
    confineRSliderToSampleBound(5);
    
    //setData(false);
    //addData();
    loop();
  }
  
  else if(onSlider){
    
    int w = rtimeSliderPos - ltimeSliderPos;
    ltimeSliderPos = mouseX - devMouse_LeftSlider;
    rtimeSliderPos = ltimeSliderPos + w;
    
    confineRSliderToBound(10);
    //confineLSliderToBound();
    confineSliderToBound(w);
    //confineSliderToSampleBound(5);

//    setData(false);
//    addData();
    loop();
    
  } 
  
  //-------------------------
  
  else if(isLHueSlider){
    lhueSliderPos = mouseX - hueSliderDimX/2;
    confineLSliderToHueBound(5);
    colorLayers();
    loop();
  }
  
  else if(isRHueSlider){
    rhueSliderPos = mouseX - hueSliderDimX/2;
    confineRSliderToHueBound(5);
//    setData();
//    addData();
    colorLayers();
    loop();
  }
  
  else if(onHueSlider){
    
    int w = rhueSliderPos - lhueSliderPos;
    lhueSliderPos = mouseX - devMouse_LeftHueSlider;
    rhueSliderPos = lhueSliderPos + w;
    
    confineRSliderToHueBound(5);
    //confineLSliderToBound();
    confineSliderToHueBound(w);
    colorLayers();
//    setData();
//    addData();
    loop();
    
  } 

//-------------------------
  
  else if(isLLumaSlider){
    llumaSliderPos = mouseX - lumaSliderDimX/2;
    confineLSliderToLumaBound(5);
    colorLayers();
    loop();
  }
  
  else if(isRLumaSlider){
    rlumaSliderPos = mouseX - lumaSliderDimX/2;
    confineRSliderToLumaBound(5);
//    setData();
//    addData();
    colorLayers();
    loop();
  }
  
  else if(onLumaSlider){
    
    int w = rlumaSliderPos - llumaSliderPos;
    llumaSliderPos = mouseX - devMouse_LeftLumaSlider;
    rlumaSliderPos = llumaSliderPos + w;
    
    confineRSliderToLumaBound(5);
    //confineLSliderToBound();
    confineSliderToLumaBound(w);
    colorLayers();
//    setData();
//    addData();
    loop();
    
  } 
  
  //-------------------------
  
  else if(isLChromaSlider){
    lchromaSliderPos = mouseX - chromaSliderDimX/2;
    confineLSliderToChromaBound(5);
    colorLayers();
    loop();
  }
  
  else if(isRChromaSlider){
    rchromaSliderPos = mouseX - chromaSliderDimX/2;
    confineRSliderToChromaBound(5);
//    setData();
//    addData();
    colorLayers();
    loop();
  }
  
  else if(onChromaSlider){
    
    int w = rchromaSliderPos - lchromaSliderPos;
    lchromaSliderPos = mouseX - devMouse_LeftChromaSlider;
    rchromaSliderPos = lchromaSliderPos + w;
    
    confineRSliderToChromaBound(5);
    //confineLSliderToBound();
    confineSliderToChromaBound(w);
    colorLayers();
//    setData();
//    addData();
    loop();
    
  } 
  
   //-------------------------
  
  else if( onnumDivSlider ){
    
    numDivSliderPos = mouseX;
    confinenumDivSliderToBound();
    confineLSliderToSampleBound(5);
    confineRSliderToSampleBound(5);
    
    calculateNumDivisions();

  }
  
  //-------------------------
  
    else if(isLNumFiltersSlider){
      lnumFiltersSliderPos = mouseX - numFiltersSliderDimX/2;
      confineLSliderToNumFiltersBound(20);
      calculateNumFilters();
    }
  
  else if(isRNumFiltersSlider){
    rnumFiltersSliderPos = mouseX - numFiltersSliderDimX/2;
    confineRSliderToNumFiltersBound(20);
    calculateNumFilters();
  }
  
  else if(onNumFiltersSlider){
    
    int w = rnumFiltersSliderPos - lnumFiltersSliderPos;
    lnumFiltersSliderPos = mouseX - devMouse_LeftNumFiltersSlider;
    rnumFiltersSliderPos = lnumFiltersSliderPos + w;
    
    confineRSliderToNumFiltersBound(20);
    //confineLSliderToBound();
    confineSliderToNumFiltersBound(w);
    calculateNumFilters();
    
  }
  
}


void mouseMoved(){

  // highlighted point in trend plot
  if(drawTrend() && withinMainPlotBounds()) {
    
    //calculate range first
    int low = (int)map(ltimeSliderPos, timeScrollBarX1, timeScrollBarX2, 0, controller.numData);
    int upper = (int)map(rtimeSliderPos, timeScrollBarX1, timeScrollBarX2, 0, controller.numData); 
    ////////////////////////////
    boolean found = false;
    for (int layerID = 0; layerID < controller.numLayers/2; layerID++) {
      if(found) break;
      for(int pos = low; pos < upper; pos++){       
        float value =  controller.getUpperData(layerID, pos) - controller.getLowerData(layerID, pos);
        float x = map(pos, low, upper - 1, mainPlotX1, mainPlotX2);
        float y = map(value, 0, computeTrendDataMax(), mainPlotY2 - 20, mainPlotY1 + 20);
    
        if(abs(mouseX-x) < 10 && abs(mouseY-y) < 10) {
          highlightedPoint = layerID;
          highlightedPointPos = pos;
          found = true;
          loop();
          break;
        }
      }
    }
    
    if(!found) {
      for (int layerID = controller.numLayers - 1; layerID >= ceil(controller.numLayers/2); layerID--) {
        if(found) break;
        for(int pos = low; pos < upper; pos++){       
          float value =  controller.getUpperData(layerID, pos) - controller.getLowerData(layerID, pos);
          float x = map(pos, low, upper - 1, mainPlotX1, mainPlotX2);
          float y = map(value, 0, computeTrendDataMax(), mainPlotY2 - 20, mainPlotY1 + 20);
      
          if(abs(mouseX-x) < 10 && abs(mouseY-y) < 10) {
            highlightedPoint = layerID;
            highlightedPointPos = pos;
            found = true;
            loop();
            break;
          }
        }
      }
    }
    
    if(!found) highlightedPoint = -1;
    
  }else {
    highlightedPoint = -1;
  }
  
  
  if(withinFilterBounds()){
    int prevID = highlightedLayer;
    float dimy = (filterY2 - filterY1) / numFilters;
    int j = floor( (mouseY-filterY1)/dimy);
    
    j = numFilters - j - 1;
    
    int layerID = controller.matchLayerID(j);
    if(layerID >= controller.numLayers) return;
    highlightedLayer = layerID;
    
    if(drawTrend()) loop();
    
    if(!drawTrend() && highlightedLayer!= - 1 && filtersChosen[j]!= 0) {
         //println("Highlighted Layer: " + highlightedLayer);
         controller.setHighlightColor(highlightedLayer, 0xFFFFFFFF);
         
          color c = controller.getColor(highlightedLayer);
          float r = red(c), g = green(c), b = blue(c);
          
          if( r >= 150 && g >= 150 && b >= 150) 
              controller.setHighlightColor(highlightedLayer, 0xFF000000);
              
          if(prevID != -1 && prevID != highlightedLayer) controller.setHighlightColor(prevID, controller.getColor(prevID));

      loop();
     
      }
  }else if(!withinFilterBounds()){
    //println("Out of bOUNDS");
    if(highlightedLayer != -1){
       controller.setHighlightColor(highlightedLayer, controller.getColor(highlightedLayer)); 
    }
      highlightedLayer = -1;
  }
  
  if(withinMainPlotBounds() && !drawTrend()){
    
//    /println(highlightedLayer);
    int prevID = highlightedLayer;
    highlightedLayer = -1;
    
    int low = (int)map(ltimeSliderPos, timeScrollBarX1, timeScrollBarX2, 0, controller.numData);
    int upper = (int)map(rtimeSliderPos, timeScrollBarX1, timeScrollBarX2, 0, controller.numData);  

    int mouse_x = 0;
    int mouse_y = 0;
    float m = (float)(mainPlotX2 - mainPlotX1) / (upper - low - 1);
    m *= 0.5;
    //println("m : " + m);
   for (int layerID = controller.numLayers - 1; layerID >= 0; layerID--) {
    
    for(int pos = low; pos < upper; pos++){
      float u =  controller.getUpperData(layerID, pos);//controller.getg0(pos) + controller.getUpperOffset(layerID, pos);
      float l =  controller.getLowerData(layerID, pos);//controller.getg0(pos) + controller.getLowerOffset(layerID, pos);
      float x = map(pos, low, upper - 1, mainPlotX1, mainPlotX2);
      float yu = map(u, dataMin, dataMax, mainPlotY2 , mainPlotY1);
      float yl = map(l, dataMin, dataMax, mainPlotY2 , mainPlotY1);

      if (withinCustomBounds(x - m, x + m, yu, yl)){
       highlightedLayer = layerID;
       mouse_x = (int)x;
       mouse_y = (int)yu;
       
       //point(x, yu);
       //break;
       //loop();
      } 
    }
   }
   
     //rect(x1, y1, x2, y2);
   
   if(highlightedLayer!= - 1) {
       controller.setHighlightColor(highlightedLayer, 0xFFFFFFFF);
       
        color c = controller.getColor(highlightedLayer);
        float r = red(c), g = green(c), b = blue(c);
        
        if( r >= 150 && g >= 150 && b >= 150)  controller.setHighlightColor(highlightedLayer, 0xFF000000);
   }
   if(prevID != -1 && prevID != highlightedLayer) controller.setHighlightColor(prevID, controller.getColor(prevID));
//   if(prevID == layerIDtoStroke) layerIDtoStroke = -1;
    if(highlightedLayer != -1) loop();
  }else if(!withinFilterBounds()){
    if(highlightedLayer != -1){
       controller.setHighlightColor(highlightedLayer, controller.getColor(highlightedLayer)); 
    }
      highlightedLayer = -1;
  }
  
}

void mouseReleased(){
  if(onFilter) onFilter = false;
  
  if(isLTimeSlider) isLTimeSlider = false;
  if(isRTimeSlider) isRTimeSlider = false;
  if(onSlider) onSlider = false;
  
  if(isLHueSlider) isLHueSlider = false;
  if(isRHueSlider) isRHueSlider = false;
  if(onHueSlider) onHueSlider = false;
  
  if(isLLumaSlider) isLLumaSlider = false;
  if(isRLumaSlider) isRLumaSlider = false;
  if(onLumaSlider) onLumaSlider = false;
  
  if(isLChromaSlider) isLChromaSlider = false;
  if(isRChromaSlider) isRChromaSlider = false;
  if(onChromaSlider) onChromaSlider = false;
  
  if(onnumDivSlider) onnumDivSlider = false;
  
  if(isLNumFiltersSlider) isLNumFiltersSlider = false;
  if(isRNumFiltersSlider) isRNumFiltersSlider = false;
  if(onNumFiltersSlider) onNumFiltersSlider = false;
}

//* --------------------------------------------
//* Key Functions ------------------------------
//* --------------------------------------------
//* --------------------------------------------

void keyPressed(){
  if (key == 't'){
    updateOption();
    loop();
  }
  
   if (key == CODED) {
     
     if (keyCode == RIGHT) {
       graphMode++;
       if(graphMode == 4) graphMode = 0;
       addData();
       computeDataMinMax();
     }
     
     if (keyCode == LEFT) {
       graphMode--;
       if(graphMode == -1) graphMode = 3;
       addData();
       computeDataMinMax();
     }
   }
}
